﻿using PGMHelper;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace CrackPrj
{


    /// <summary>
    /// 构件
    /// </summary>
    public class Specimen
    {
        /// <summary>
        /// 试件名称
        /// </summary>
        public string Name { set; get; }

        /// <summary>
        /// 峰值承载力
        /// </summary>
        public double MaxCapacity { set; get; }

        /// <summary>
        /// 试件的矩形包围框
        /// </summary>
        public Tuple<Node, Node> BoundRect { set; get; }

        /// <summary>
        /// 不同状态
        /// </summary>
        public List<SpecimenState> StateList { set; get; }

        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="directPath"></param>
        public void ToFile(string directPath)
        {
            //序列化
            var str = JsonConvert.SerializeObject(this);
            //文件名
            var filePath = string.Format("{0}\\{1}.json", directPath, this.Name);
            //导出文件
            File.WriteAllText(filePath, str);
        }

        /// <summary>
        /// 添加状态
        /// </summary>
        /// <param name="state"></param>
        public void Add(SpecimenState state)
        {
            this.StateList.Add(state);
        }

        /// <summary>
        /// 获得绘图对象
        /// </summary>
        /// <returns></returns>
        public void ToGraphics(int stateIndex, PictureBox pb)
        {
            //创建对象
            var chart2D = new Chart2D();
            //添加包围框
            var brObj = new Chart2DObject(Color.LightGray);
            //添加点
            var ptI = this.BoundRect.Item1.GetPoint();
            var ptJ = new Point(this.BoundRect.Item2.intX, this.BoundRect.Item1.intY);
            var ptK = this.BoundRect.Item2.GetPoint();
            var ptL = new Point(this.BoundRect.Item1.intX, this.BoundRect.Item2.intY);
            //添加点
            brObj.Add(ptI); brObj.Add(ptJ); brObj.Add(ptK); brObj.Add(ptL);
            //添加对象
            chart2D.Add(brObj);
            //判断对象是否存在
            if (stateIndex < this.StateList.Count)
                this.StateList[stateIndex].ToChart2D(chart2D);
            //绘图
            chart2D.ToGraphics(pb);
        }

        /// <summary>
        /// 获得构件
        /// </summary>
        /// <param name="specimen"></param>
        /// <returns></returns>
        public static bool GetSpecimen(out Specimen specimen)
        {
            //初始化
            specimen = new Specimen();
            //选择文件
            string filePath = string.Empty;
            if (!WilsonHelper.OpenFile("json|*.json|json|*.*", ref filePath)) return false;
            //反序列化
            var str = File.ReadAllText(filePath);
            specimen = JsonConvert.DeserializeObject<Specimen>(str);
            return true;
        }

        /// <summary>
        /// 初始构造函数
        /// </summary>
        public Specimen()
        {
            this.Name = string.Empty;
            this.BoundRect = Tuple.Create<Node, Node>(new Node(), new Node());
            this.StateList = new List<SpecimenState>();
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name"></param>
        /// <param name="xi"></param>
        /// <param name="yi"></param>
        /// <param name="xj"></param>
        /// <param name="yj"></param>
        public Specimen(string name, double maxCapacity, double xi, double yi, double xj, double yj): this()
        {
            //构件名称
            this.Name = name;
            //承载力
            this.MaxCapacity = maxCapacity;
            //包围框
            var nodeI = new Node(Math.Min(xi, xj), Math.Min(yi, yj));
            var nodeJ = new Node(Math.Max(xi, xj), Math.Max(yi, yj));
            this.BoundRect = Tuple.Create<Node, Node>(nodeI, nodeJ);
        }
    }

    /// <summary>
    /// 试件状态
    /// </summary>
    public class SpecimenState
    {
        /// <summary>
        /// 承载力系数
        /// </summary>
        public double CapacityRatio { set; get; }

        /// <summary>
        /// 裂缝集合
        /// </summary>
        public List<Crack> CrackList { set; get; }

        /// <summary>
        /// 压溃集合
        /// </summary>
        public List<Crush> CrushList { set; get; }

        /// <summary>
        /// 添加裂缝
        /// </summary>
        /// <param name="crack"></param>
        public void Add(Crack crack)
        {
            this.CrackList.Add(crack);
        }

        /// <summary>
        /// 添加压溃区
        /// </summary>
        /// <param name="crush"></param>
        public void Add(Crush crush)
        {
            this.CrushList.Add(crush);
        }

        /// <summary>
        /// 添加绘图对象
        /// </summary>
        /// <param name="chart2D"></param>
        public void ToChart2D(Chart2D chart2D)
        {
            //添加裂缝
            this.CrackList.ForEach(crack => chart2D.Add(crack.GetChart2DObject()));
            //添加压溃区
            this.CrushList.ForEach(crush => chart2D.Add(crush.GetChart2DObject()));
        }

        /// <summary>
        /// 试件状态
        /// </summary>
        public SpecimenState()
        {
            this.CrackList = new List<Crack>();
            this.CrushList = new List<Crush>();
        }

        /// <summary>
        /// 试件状态
        /// </summary>
        /// <param name="capacityRatio"></param>
        public SpecimenState(double capacityRatio):this()
        {
            this.CapacityRatio = capacityRatio;
        }
    }

    /// <summary>
    /// 裂缝
    /// </summary>
    public class Crack
    {
        /// <summary>
        /// 点列表
        /// </summary>
        public List<Node> CrakPointList { set; get; }

        /// <summary>
        /// 裂缝
        /// </summary>
        /// <returns></returns>
        public Chart2DObject GetChart2DObject()
        {
            //直线
            var line = new Chart2DLine(Color.Red, 2);
            //添加点
            this.CrakPointList.ForEach(node => line.Add(node.GetPoint()));
            //返回直线
            return line;
        }

        /// <summary>
        /// 添加裂缝点
        /// </summary>
        /// <param name="node"></param>
        public void Add(Node node)
        {
            this.CrakPointList.Add(node);
        }

        /// <summary>
        /// 构造裂缝
        /// </summary>
        public Crack()
        {
            this.CrakPointList = new List<Node>();
        }
    }

    /// <summary>
    /// 压溃
    /// </summary>
    public class Crush
    {
        /// <summary>
        /// 点列表
        /// </summary>
        public List<Node> CrushPointList { set; get; }

        /// <summary>
        /// 裂缝
        /// </summary>
        /// <returns></returns>
        public Chart2DObject GetChart2DObject()
        {
            //直线
            var line = new Chart2DObject(Color.Blue);
            //添加点
            this.CrushPointList.ForEach(node => line.Add(node.GetPoint()));
            //返回直线
            return line;
        }

        /// <summary>
        /// 添加裂缝点
        /// </summary>
        /// <param name="node"></param>
        public void Add(Node node)
        {
            this.CrushPointList.Add(node);
        }

        /// <summary>
        /// 构造裂缝
        /// </summary>
        public Crush()
        {
            this.CrushPointList = new List<Node>();
        }
    }

    /// <summary>
    /// 节点
    /// </summary>
    public class Node
    {
        /// <summary>
        /// 二维X坐标
        /// </summary>
        public double X { set; get; }

        /// <summary>
        /// 二维Y坐标
        /// </summary>
        public double Y { set; get; }

        [JsonIgnore]
        /// <summary>
        /// 二维X坐标 整形
        /// </summary>
        public int intX
        {
            get
            {
                return Convert.ToInt32(this.X);
            }
        }

        [JsonIgnore]
        /// <summary>
        /// 二维Y坐标 整形
        /// </summary>
        public int intY
        {
            get
            {
                return Convert.ToInt32(this.Y);
            }
        }

        /// <summary>
        /// 获得点
        /// </summary>
        /// <returns></returns>
        public Point GetPoint()
        {
            return new Point(this.intX, this.intY);
        }

        /// <summary>
        /// 构造节点
        /// </summary>
        public Node()
        {

        }

        /// <summary>
        /// 构造节点
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public Node(double x, double y)
        {
            this.X = x;
            this.Y = y;
        }
    }
}
